home *** CD-ROM | disk | FTP | other *** search
- /* IFF images
- *
- * dieter fiebelkorn 13.05.91
- *
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
- #include <vdi.h>
- #include <aes.h>
- #include "image.h"
- #include "imageopt.h"
- #include "module.h"
- #include "iff.h"
-
- extern char *DupString(LOAD_Structure *loadS, char *s);
-
-
- COLOR_ENTRY color_map[256];
-
- static int loadIffMonoCompressed(ZFILE *zf, LOAD_Structure *loadS, char *data,
- unsigned int width, unsigned int height)
- {
- unsigned char wert, run;
- signed char command;
- long read, toRead;
-
- toRead = (width >> 3) + ((width & 0x0007) ? 1 : 0);
- toRead *= height;
- read = 0UL;
- do {
- command = (signed char) (*loadS->input.getchr)(zf);
- if (command == -128) {
- (*loadS->input.close)(zf);
- (*loadS->print.printout)("DegasLoad: Bad read on image data\n");
- return(-1);
- }
- if (command < 0) {
- wert = (unsigned char) (*loadS->input.getchr)(zf);
- for (run = 0; run < -command+1; run++, read++)
- *data++ = wert;
- }
- else {
- for (run = 0; run < command+1; run++, read++) {
- wert = (unsigned char) (*loadS->input.getchr)(zf);
- *data++ = wert;
- }
- }
- } while (read < toRead);
- return(0);
- }
-
-
-
- static int loadIffColorCompressed(ZFILE *zf, LOAD_Structure *loadS, char *data,
- unsigned int width, unsigned int height,
- unsigned int planes, unsigned int ismask)
- {
- unsigned char wert, run,
- buffer[BUFSIZ];
- signed char command, warning;
- long read;
- unsigned long x, y, plane, offs;
- unsigned long set_bit, mask;
-
- warning = '\0';
- for (y= 0; y < height; y++) {
- for (plane= 0; plane < planes+(ismask!=0); plane++) {
- read = 0UL;
- do {
- command = (signed char) (*loadS->input.getchr)(zf);
- if (command == -128)
- continue;
-
- if (command < 0) {
- wert = (unsigned char) (*loadS->input.getchr)(zf);
- for (run = 0; run < -command+1; run++, read++)
- buffer[read] = wert;
- }
- else {
- for (run = 0; run < command+1; run++, read++) {
- wert = (unsigned char) (*loadS->input.getchr)(zf);
- buffer[read] = wert;
- }
- }
- } while (read < width/8);
-
- if (read > width/8 && warning == '\0')
- {
- (*loadS->print.printout)(" \034\001Warning:\034\100 Incorrect length of decoded scanline\n");
- warning = '\x01';
- }
-
- if (plane < planes) {
- set_bit = 1U << plane;
- for (x= 0; x < width/8; x++) {
- mask = 0x80;
- offs = 0;
- do {
- if (buffer[x] & mask)
- data[8UL * x + offs] |= set_bit;
- mask >>= 1;
- offs++;
- } while(mask);
- }
- }
- }
- data += width;
- }
- return(0);
- }
-
-
-
- static void loadIffMonoUnCompressed(ZFILE *zf, LOAD_Structure *loadS, char *data,
- unsigned int width, unsigned int height)
- {
- unsigned long toRead;
-
- toRead = (width >> 3) + ((width & 0x0007) ? 1 : 0);
- toRead *= height;
- (*loadS->input.read)(zf, data, toRead);
- }
-
-
-
- static int loadIffColorUnCompressed(ZFILE *zf, LOAD_Structure *loadS, char *data,
- unsigned int width, unsigned int height,
- unsigned int planes, unsigned int ismask)
- {
- long x, y;
- unsigned int buffer, plane;
- unsigned int mask, offs;
-
- for (y= 0; y < height; y++) {
- for (plane= 0; plane < planes+(ismask!=0); plane++) {
- for (x= 0; x < width/16; x++) {
- if ((*loadS->input.read)(zf, &buffer, 2UL) < 2UL) {
- (*loadS->error.printerr)(" Error reading IFF!");
- (*loadS->input.close)(zf);
- return(-1);
- }
- if (plane < planes) {
- mask = 0x8000;
- offs = 0;
- while (mask) {
- if (buffer & mask)
- data[16*x + offs] |= 1U << plane;
- mask >>= 1;
- offs++;
- }
- }
- }
- }
- data += width;
- }
- return(0);
- }
-
-
-
- static loadIffHam(ZFILE *zf, LOAD_Structure *loadS, char *data,
- unsigned int width, unsigned int height, unsigned int alignwidth,
- unsigned int planes, unsigned int compressed)
- {
- COLOR_ENTRY color;
- unsigned char *new_data;
- unsigned int skip, x, y;
- unsigned int op_shift, col_shift;
- unsigned char op, col, col_mask;
-
- new_data = data + 2L * width * height;
- if (compressed)
- loadIffColorCompressed(zf, loadS, new_data, width, height, planes, 0);
- else
- loadIffColorUnCompressed(zf, loadS, new_data, width, height, planes, 0);
-
- if (planes != 6 && planes != 8)
- return(0);
-
- color.red = 0;
- color.green = 0;
- color.blue = 0;
-
- if (planes == 6) {
- op_shift = 4;
- col_mask = 0x0F;
- col_shift = 4;
- }
- if (planes == 8) {
- op_shift = 6;
- col_mask = 0x3F;
- col_shift = 2;
- }
-
- skip = alignwidth - width;
- for (y= 0; y < height; y++) {
- for (x= 0; x < width; x++) {
- op = *new_data >> op_shift;
- col = *new_data & col_mask;
- if (op == 0) {
- color.red = color_map[(int)col].red;
- color.green = color_map[(int)col].green;
- color.blue = color_map[(int)col].blue;
- }
- if (op == 2) {
- color.red = col << col_shift;
- }
- if (op == 3) {
- color.green = col << col_shift;
- }
- if (op == 1) {
- color.blue = col << col_shift;
- }
- *data++ = color.red;
- *data++ = color.green;
- *data++ = color.blue;
- new_data++;
- }
- data += 3L * skip;
- }
- return(0);
- }
-
-
-
- int iffIdent(LOAD_Structure *loadS, unsigned int verbose)
- {
- ZFILE *zf;
- IFF_HEADER iffheader;
- CHUNK_HEADER chunkheader;
- BITMAP_HEADER bitmapheader;
- int found_camgchunk,
- found_bitmapheader;
- long i;
- char *fullname = loadS->in_filename;
-
- if ((zf= (*loadS->input.open)(fullname, 0x00)) != NULL) {
- (*loadS->input.read)(zf, &iffheader, sizeof(iffheader));
-
- while ((*(long*)&iffheader.form_id == 'FORM') && (*(long*)&iffheader.file_id != 'ILBM')) {
- (*loadS->input.skip)(zf, iffheader.lenght);
- if ((*loadS->input.read)(zf, &iffheader, sizeof(iffheader)) != sizeof(iffheader)) {
- (*loadS->input.close)(zf);
- return(0);
- }
- }
- if ((*(long*)&iffheader.form_id != 'FORM') || (*(long*)&iffheader.file_id != 'ILBM')) {
- (*loadS->input.close)(zf);
- return(0);
- }
-
- found_camgchunk = 0;
- found_bitmapheader = 0;
-
- while(1) {
- (*loadS->input.read)(zf, &chunkheader, sizeof(chunkheader));
- if ((!isupper(chunkheader.chunk_id[0]) && chunkheader.chunk_id[0] != ' ') ||
- (!isupper(chunkheader.chunk_id[1]) && chunkheader.chunk_id[1] != ' ') ||
- (!isupper(chunkheader.chunk_id[2]) && chunkheader.chunk_id[2] != ' ') ) {
- (*loadS->error.printerr)(" Error reading IFF!");
- break;
- }
- if (*(long*)&chunkheader.chunk_id == 'CAMG') {
- (*loadS->input.read)(zf, &i, sizeof(long));
- if (i & 0x00000800L)
- found_camgchunk = 1;
- continue;
- }
- if (*(long*)&chunkheader.chunk_id == 'BMHD')
- {
- (*loadS->input.read)(zf, &bitmapheader, sizeof(bitmapheader));
- found_bitmapheader = 1;
- continue;
- }
- if (*(long*)&chunkheader.chunk_id == 'BODY')
- {
- if (bitmapheader.planes == 1)
- (*loadS->print.printout)("%s\n is a %dx%d monochrome/duochrome IFF-image\n", fullname,
- bitmapheader.width, bitmapheader.height);
- else
- if (found_camgchunk == 1 && (bitmapheader.planes == 6 || bitmapheader.planes == 8))
- (*loadS->print.printout)("%s\n is a %dx%d HAM-IFF-image\n", fullname,
- bitmapheader.width, bitmapheader.height);
- else
- (*loadS->print.printout)("%s\n is a %dx%d IFF-image with %d colors\n", fullname,
- bitmapheader.width, bitmapheader.height, 1U << bitmapheader.planes);
-
- (*loadS->input.close)(zf);
- return(found_bitmapheader);
- }
- (*loadS->input.skip)(zf, chunkheader.lenght);
- }
- }
- (*loadS->input.close)(zf);
- return(0);
- }
-
-
-
- Image *iffLoad(LOAD_Structure *loadS, unsigned int verbose)
- {
- ZFILE *zf;
- Image *image = NULL;
- IFF_HEADER iffheader;
- CHUNK_HEADER chunkheader;
- BITMAP_HEADER bitmapheader;
- int found_bitmapheader;
- int found_camgchunk;
- int found_cmapchunk;
- int bw_pict;
- long map_colors, colors,
- max_colors, i;
- unsigned long factor;
- char *fullname = loadS->in_filename;
- int id_only = loadS->identify_only;
-
- found_bitmapheader = 0;
- map_colors = 0;
- max_colors = 8;
-
- if (id_only)
- return((Image*)iffIdent(loadS, verbose));
-
- if (iffIdent(loadS, verbose) == 0)
- return(NULL);
-
- if ((zf= (*loadS->input.open)(fullname, 0x00)) == 0) {
- (*loadS->error.printerr)(" Error reading IFF!");
- return(NULL);
- }
- (*loadS->input.read)(zf, &iffheader, sizeof(iffheader));
- while ((*(long*)&iffheader.form_id == 'FORM') && (*(long*)&iffheader.file_id != 'ILBM')) {
- (*loadS->input.skip)(zf, iffheader.lenght);
- if ((*loadS->input.read)(zf, &iffheader, sizeof(iffheader)) != sizeof(iffheader)) {
- (*loadS->input.close)(zf);
- return(0);
- }
- }
-
- found_bitmapheader = 0;
- found_camgchunk = 0;
- found_cmapchunk = 0;
- while (1) {
- (*loadS->input.read)(zf, &chunkheader, sizeof(chunkheader));
- if ((!isupper(chunkheader.chunk_id[0]) && chunkheader.chunk_id[0] != ' ') ||
- (!isupper(chunkheader.chunk_id[1]) && chunkheader.chunk_id[1] != ' ') ||
- (!isupper(chunkheader.chunk_id[2]) && chunkheader.chunk_id[2] != ' ') ) {
- (*loadS->error.printerr)(" Error reading IFF!");
- if (image)
- (*loadS->images.freeGVImage)(image);
- image = NULL;
- (*loadS->input.close)(zf);
- return(image);
- }
- if (*(long*)&chunkheader.chunk_id == 'BMHD')
- {
- found_bitmapheader = 1;
- (*loadS->input.read)(zf, &bitmapheader, sizeof(bitmapheader));
- if (bitmapheader.planes > 8) {
- (*loadS->print.printout)(" Don't support more then 8 planes");
- (*loadS->input.close)(zf);
- return(NULL);
- }
- if (bitmapheader.compressed > 1) {
- (*loadS->print.printout)(" Don't supported compression algorithm");
- (*loadS->input.close)(zf);
- return(NULL);
- }
- if ((bitmapheader.planes == 1) && (bitmapheader.mask & 0x01)) {
- (*loadS->print.printout)(" Don't support monochrome Images with _mask_");
- (*loadS->input.close)(zf);
- return(NULL);
- }
- continue;
- }
- if (*(long*)&chunkheader.chunk_id == 'CMAP')
- {
- map_colors = chunkheader.lenght / 3;
- if (map_colors > 256) {
- (*loadS->print.printout)(" Don't support more then 256 colors");
- (*loadS->input.close)(zf);
- return(NULL);
- }
- found_cmapchunk = 1;
- if (map_colors <= 2)
- bw_pict = 1;
- for (i = 0; i < map_colors; i++) {
- (*loadS->input.read)(zf, &(color_map[i]), 3UL /*sizeof(COLOR_ENTRY)*/);
- if (max_colors < 256) {
- if (max_colors < 16) {
- if ((color_map[i].red > 7) || (color_map[i].green > 7) || (color_map[i].blue > 7))
- max_colors = 16;
- }
- if ((color_map[i].red > 15) || (color_map[i].green > 15) || (color_map[i].blue > 15))
- max_colors = 256;
- }
- if (bw_pict == 1) {
- switch((int)max_colors)
- {
- case 8:
- bw_pict &= (color_map[i].red >= 7 && color_map[i].green >= 7 && color_map[i].blue >= 7)
- || (color_map[i].red <= 0 && color_map[i].green <= 0 && color_map[i].blue <= 0);
- break;
- case 16:
- bw_pict &= (color_map[i].red >= 15 && color_map[i].green >= 15 && color_map[i].blue >= 15)
- || (color_map[i].red <= 0 && color_map[i].green <= 0 && color_map[i].blue <= 0);
- break;
- case 256:
- bw_pict &= (color_map[i].red >= 254 && color_map[i].green >= 254 && color_map[i].blue >= 254)
- || (color_map[i].red <= 0 && color_map[i].green <= 0 && color_map[i].blue <= 0);
- break;
- }
- }
- }
- continue;
- }
- if (*(long*)&chunkheader.chunk_id == 'CAMG') {
- (*loadS->input.read)(zf, &i, sizeof(long));
- if (i & 0x00000800L)
- found_camgchunk = 1;
- continue;
- }
-
- if (*(long*)&chunkheader.chunk_id == 'BODY') {
- if (found_bitmapheader) {
- if (bitmapheader.planes == 1 && (found_cmapchunk == 0 || bw_pict != 0)) {
- if ((bitmapheader.width == 0) ||
- (bitmapheader.height == 0)) {
- (*loadS->input.close)(zf);
- return (NULL);
- }
-
- image = (*loadS->images.newBitImage)(NULL, (unsigned int) bitmapheader.width, (unsigned int) bitmapheader.height);
- if (!image) {
- (*loadS->input.close)(zf);
- return (image);
- }
-
- if (bitmapheader.width % 16)
- {
- image->unalignwidth = bitmapheader.width;
- image->width = (bitmapheader.width += 16 - (bitmapheader.width % 16));
- }
- if (bitmapheader.compressed)
- loadIffMonoCompressed(zf, loadS, image->data, bitmapheader.width, bitmapheader.height);
- else
- loadIffMonoUnCompressed(zf, loadS, image->data, bitmapheader.width, bitmapheader.height);
- }
- else
- {
- if ((bitmapheader.width == 0) ||
- (bitmapheader.height == 0) ||
- (bitmapheader.planes == 0)) {
- (*loadS->input.close)(zf);
- return (NULL);
- }
-
- if (found_camgchunk == 0 || (bitmapheader.planes != 6 && bitmapheader.planes != 8))
- image = (*loadS->images.newRGBImage)(NULL, (unsigned int) bitmapheader.width, (unsigned int) bitmapheader.height, bitmapheader.planes);
- else
- image = (*loadS->images.newTCImage)(NULL, (unsigned int) bitmapheader.width, (unsigned int) bitmapheader.height);
- if (!image) {
- (*loadS->input.close)(zf);
- return (image);
- }
-
- if (bitmapheader.width % 16)
- {
- image->unalignwidth = bitmapheader.width;
- image->width = (bitmapheader.width += 16 - (bitmapheader.width % 16));
- }
-
- if (found_camgchunk == 1 && (bitmapheader.planes == 6 || bitmapheader.planes == 8)) {
- if (loadIffHam(zf, loadS, image->data, bitmapheader.width, bitmapheader.height, image->width, bitmapheader.planes, bitmapheader.compressed)) {
- (*loadS->images.freeGVImage)(image);
- image = NULL;
- }
- if (image)
- image->title= DupString(loadS, fullname);
- (*loadS->input.close)(zf);
- return(image);
- }
-
- image->rgb.red [ 0]= 0xFF00;
- image->rgb.green[ 0]= 0xFF00;
- image->rgb.blue [ 0]= 0xFF00;
- colors = 1U << bitmapheader.planes;
- switch((int)max_colors)
- {
- case 8:
- factor = 364;
- break;
- case 16:
- factor = 170;
- break;
- case 256:
- factor = 10;
- break;
- }
-
- if (map_colors > colors)
- map_colors = colors;
-
- /* colors -= map_colors;
- */ for (i = 0; i < map_colors; i++) {
- image->rgb.red[i] = ((int) (factor * color_map[i].red / 10)) << 8;
- image->rgb.green[i] = ((int) (factor * color_map[i].green / 10)) << 8;
- image->rgb.blue[i] = ((int) (factor * color_map[i].blue / 10)) << 8;
- }
- image->rgb.used = (int)map_colors;
- for (/* i = 0 */; i < colors; i++) {
- image->rgb.red[i] = 0x0000;
- image->rgb.green[i] = 0x0000;
- image->rgb.blue[i] = 0x0000;
- }
- if (bitmapheader.compressed)
- loadIffColorCompressed(zf, loadS, image->data, bitmapheader.width, bitmapheader.height, bitmapheader.planes, bitmapheader.mask & 0x01);
- else
- if (loadIffColorUnCompressed(zf, loadS, image->data, bitmapheader.width, bitmapheader.height, bitmapheader.planes, bitmapheader.mask & 0x01) == -1) {
- (*loadS->images.freeGVImage)(image);
- image = NULL;
- (*loadS->input.close)(zf);
- return(image);
- }
- }
- }
- break;
- }
- (*loadS->input.skip)(zf, chunkheader.lenght);
- }
-
- if (image)
- image->title= DupString(loadS, fullname);
-
- (*loadS->input.close)(zf);
- return(image);
- }
-